package com.scott.failfast;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.*;

/**
 * java fail-fast机制测试
 * <p>
 * Fail-fast事件产生的条件：
 * 当多个线程对Collection进行操作的时候，如果其中一个线程通过iterator去遍历集合时，该集合的内容被其他线程所改变，则会抛出ConcurrentModificationException异常
 * 解决办法：
 * JUC包下的响应类处理，例如 {@link java.util.concurrent.CopyOnWriteArrayList} {@link java.util.concurrent.CopyOnWriteArraySet} etc.
 *
 * @author Scott 2017/11/8 16:01
 */
public class FailFastTest {

    // 可能产生fail-fast异常事件
    private static List<String> list = new ArrayList<>();

    public static void main(String[] args) {
        ExecutorService service = Executors.newFixedThreadPool(2);
        List<RunTaskOne> list = new ArrayList<>();
        RunTaskOne one = new RunTaskOne();
        list.add(one);
        RunTaskOne two = new RunTaskOne();
        list.add(two);
        try {
            List<Future<Object>> futures = service.invokeAll(list);
            while (futures.size() > 0) {
                Future future = futures.get(0);
                System.out.println("future is Done ->" + future.isDone() + "\nfuture is cancelled ->" + future.isCancelled());
                if (future.isDone()) {
                    System.out.println(Thread.currentThread().getName() + "-> " + future.get());
                    futures.remove(future);
                }
            }

        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
//            new Thread(new RunTaskOne()).start();
//            new Thread(new RunTaskTwo()).start();
        service.shutdown();

        System.out.println(list.size());

    }

    private static void printAll() {
        Iterator<String> iterator = list.iterator();

        while (iterator.hasNext()) {
            System.out.println(Thread.currentThread().getName() + " ->" + iterator.next() + " ");
        }

    }

    private static class RunTaskOne implements Callable<Object> {


        @Override
        public Object call() throws Exception {
            int i = 0;
            while (i < 100) {
                list.add(String.valueOf(i));
//                printAll();
                i++;
            }
            return i;
        }
    }

    private class RunTaskTwo implements Callable {


        @Override
        public Object call() throws Exception {
            int i = 0;
            while (i < 100) {
                list.add(String.valueOf(i));
                printAll();
                i++;
            }
            return i;
        }
    }
}
